package proxy

import (
	"bufio"
	"bytes"
	"encoding/json"
	"gopin/db"
	"io"
	"net"
	"net/http"
	"time"

	"github.com/pkg/errors"
)

type HttpContext struct {
	Request  *http.Request
	Response *http.Response
	Entity   *db.HttpEntity
}

func NewEntity(conn net.Conn) (*HttpContext, error) {
	request, err := http.ReadRequest(bufio.NewReader(conn))
	if err != nil {
		return nil, errors.Wrap(err, "请求对象生成失败")
	}
	return newEntityWithRequest(request)
}

func newEntityWithRequest(request *http.Request) (*HttpContext, error) {
	bodyBytes, err := io.ReadAll(request.Body)
	if err != nil {
		return nil, err
	}
	headers, _ := json.Marshal(request.Header)
	request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
	return &HttpContext{
		Request: request,
		Entity: &db.HttpEntity{
			Method:        request.Method,
			Host:          request.Host,
			Url:           request.URL.String(),
			Ip:            request.RemoteAddr,
			App:           "",
			RequestHeader: string(headers),
			RequestBody:   string(bodyBytes),
			RequestTime:   time.Now(),
			ResponseCode:  0,
			ResponseBody:  "",
			ResponseTime:  time.Now(),
		},
	}, nil
}

func (entity *HttpContext) SaveResponse(response *http.Response) error {

	bodyBytes, err := io.ReadAll(response.Body)
	if err != nil {
		return err
	}
	headers, _ := json.Marshal(response.Header)
	response.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
	entity.Response = response
	entity.Entity.ResponseCode = response.StatusCode
	entity.Entity.ResponseHeader = string(headers)
	entity.Entity.ResponseBody = string(bodyBytes)
	entity.Entity.ResponseTime = time.Now()
	entity.Entity.Save()
	return nil
}

func (entity *HttpContext) SetScheme(scheme string) {
	entity.Request.URL.Scheme = scheme
	entity.Entity.Scheme = scheme
}

func (entity *HttpContext) SetHost(host string) {
	entity.Request.URL.Host = host
}

func (entity *HttpContext) SetRemoteAddr(remoteAddr string) {
	entity.Request.RemoteAddr = remoteAddr
}
